// Tree-sitter parser implementation
use codegraph_core::{Parser, SyntaxTree, SyntaxNode, QueryMatch, TextEdit, Result, Position};
use async_trait::async_trait;
use tree_sitter::{Language, Tree, Node, Query, QueryCursor, Point, InputEdit};


pub struct TreeSitterParser {
    language_id: String,
    version: String,
    language: Language,
    parser: tree_sitter::Parser,
}

impl TreeSitterParser {
    pub fn new(language_id: &str, language: Language) -> Result<Self> {
        let mut parser = tree_sitter::Parser::new();
        parser.set_language(language)
            .map_err(|e| codegraph_core::CodeGraphError::parse_error(format!("Failed to set language: {}", e)))?;

        Ok(Self {
            language_id: language_id.to_string(),
            version: "0.1.0".to_string(),
            language,
            parser,
        })
    }

    pub fn python() -> Result<Self> {
        Self::new("python", tree_sitter_python::language())
    }

    pub fn javascript() -> Result<Self> {
        Self::new("javascript", tree_sitter_javascript::language())
    }

    pub fn typescript() -> Result<Self> {
        Self::new("typescript", tree_sitter_typescript::language_typescript())
    }

    pub fn rust() -> Result<Self> {
        Self::new("rust", tree_sitter_rust::language())
    }
}

#[async_trait]
impl Parser for TreeSitterParser {
    fn language_id(&self) -> &str {
        &self.language_id
    }

    fn version(&self) -> &str {
        &self.version
    }

    async fn parse(&self, source: &str, old_tree: Option<&dyn SyntaxTree>) -> Result<Box<dyn SyntaxTree>> {
        let mut parser = tree_sitter::Parser::new();
        parser.set_language(self.language)
            .map_err(|e| codegraph_core::CodeGraphError::parse_error(format!("Failed to set language: {}", e)))?;

        let old_ts_tree = old_tree
            .and_then(|t| t.as_any().downcast_ref::<TreeSitterSyntaxTree>())
            .map(|t| &t.tree);

        let tree = parser.parse(source, old_ts_tree)
            .ok_or_else(|| codegraph_core::CodeGraphError::parse_error("Failed to parse source code"))?;

        Ok(Box::new(TreeSitterSyntaxTree::new(tree, source.to_string(), self.language_id.clone())))
    }

    async fn parse_incremental(
        &self,
        edit: &TextEdit,
        old_tree: &dyn SyntaxTree,
    ) -> Result<Box<dyn SyntaxTree>> {
        let ts_tree = old_tree
            .as_any()
            .downcast_ref::<TreeSitterSyntaxTree>()
            .ok_or_else(|| codegraph_core::CodeGraphError::parse_error("Invalid tree type for incremental parsing"))?;

        let mut tree = ts_tree.tree.clone();

        let input_edit = InputEdit {
            start_byte: edit.start_byte as usize,
            old_end_byte: edit.old_end_byte as usize,
            new_end_byte: edit.new_end_byte as usize,
            start_position: Point::new(edit.start_position.row as usize, edit.start_position.column as usize),
            old_end_position: Point::new(edit.old_end_position.row as usize, edit.old_end_position.column as usize),
            new_end_position: Point::new(edit.new_end_position.row as usize, edit.new_end_position.column as usize),
        };

        tree.edit(&input_edit);

        let mut parser = tree_sitter::Parser::new();
        parser.set_language(self.language)
            .map_err(|e| codegraph_core::CodeGraphError::parse_error(format!("Failed to set language: {}", e)))?;

        let new_source = format!("{}{}", &ts_tree.source[..edit.start_byte as usize], &edit.new_text);
        let new_tree = parser.parse(&new_source, Some(&tree))
            .ok_or_else(|| codegraph_core::CodeGraphError::parse_error("Failed to parse incrementally"))?;

        Ok(Box::new(TreeSitterSyntaxTree::new(new_tree, new_source, self.language_id.clone())))
    }

    fn query(&self, pattern: &str, tree: &dyn SyntaxTree) -> Result<Vec<QueryMatch>> {
        let ts_tree = tree
            .as_any()
            .downcast_ref::<TreeSitterSyntaxTree>()
            .ok_or_else(|| codegraph_core::CodeGraphError::parse_error("Invalid tree type for query"))?;

        let query = Query::new(self.language, pattern)
            .map_err(|e| codegraph_core::CodeGraphError::parse_error(format!("Invalid query: {}", e)))?;

        let mut cursor = QueryCursor::new();
        let matches = cursor.matches(&query, ts_tree.tree.root_node(), ts_tree.source.as_bytes());

        let mut results = Vec::new();
        for m in matches {
            let mut captures = std::collections::HashMap::new();
            for capture in m.captures {
                if let Some(name) = query.capture_names().get(capture.index as usize) {
                    captures.insert(
                        name.clone(),
                        Box::new(TreeSitterSyntaxNode::new(capture.node, &ts_tree.source)) as Box<dyn SyntaxNode>
                    );
                }
            }
            results.push(QueryMatch {
                pattern_index: m.pattern_index as u32,
                captures,
            });
        }

        Ok(results)
    }

    async fn dispose(&self) -> Result<()> {
        // Tree-sitter parsers don't need explicit cleanup
        Ok(())
    }
}

pub struct TreeSitterSyntaxTree {
    pub tree: Tree,
    pub source: String,
    pub language: String,
}

impl TreeSitterSyntaxTree {
    pub fn new(tree: Tree, source: String, language: String) -> Self {
        Self {
            tree,
            source,
            language,
        }
    }
}

impl SyntaxTree for TreeSitterSyntaxTree {
    fn root_node(&self) -> Box<dyn SyntaxNode> {
        Box::new(TreeSitterSyntaxNode::new(self.tree.root_node(), &self.source))
    }

    fn query(&self, _pattern: &str) -> Result<Vec<QueryMatch>> {
        // This method is implemented in the parser for language-specific queries
        Err(codegraph_core::CodeGraphError::parse_error("Use parser.query() instead"))
    }

    fn source(&self) -> &str {
        &self.source
    }

    fn language(&self) -> &str {
        &self.language
    }

    fn as_any(&self) -> &dyn std::any::Any {
        self
    }
}

#[derive(Debug)]
pub struct TreeSitterSyntaxNode {
    kind: String,
    text: String,
    start_byte: u32,
    end_byte: u32,
    start_position: Position,
    end_position: Position,
    child_count: usize,
}

impl TreeSitterSyntaxNode {
    pub fn new(node: Node, source: &str) -> Self {
        let text = node.utf8_text(source.as_bytes()).unwrap_or("").to_string();
        let start_pos = node.start_position();
        let end_pos = node.end_position();

        Self {
            kind: node.kind().to_string(),
            text,
            start_byte: node.start_byte() as u32,
            end_byte: node.end_byte() as u32,
            start_position: Position::new(start_pos.row as u32, start_pos.column as u32),
            end_position: Position::new(end_pos.row as u32, end_pos.column as u32),
            child_count: node.child_count(),
        }
    }
}

impl SyntaxNode for TreeSitterSyntaxNode {
    fn kind(&self) -> &str {
        &self.kind
    }

    fn text(&self) -> &str {
        &self.text
    }

    fn start_byte(&self) -> u32 {
        self.start_byte
    }

    fn end_byte(&self) -> u32 {
        self.end_byte
    }

    fn start_position(&self) -> Position {
        self.start_position
    }

    fn end_position(&self) -> Position {
        self.end_position
    }

    fn children(&self) -> Vec<Box<dyn SyntaxNode>> {
        // Note: This simplified implementation doesn't provide actual children
        // In a full implementation, we'd need to store child information during construction
        Vec::new()
    }

    fn child(&self, _index: usize) -> Option<Box<dyn SyntaxNode>> {
        // Note: This simplified implementation doesn't provide actual children
        None
    }

    fn child_count(&self) -> usize {
        self.child_count
    }
}
